home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
X User Tools
/
X User Tools (O'Reilly and Associates)(1994).ISO
/
sources
/
xcalc
/
xcalc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-27
|
11KB
|
389 lines
/*
* $XConsortium: xcalc.c,v 1.15 91/02/16 19:39:37 converse Exp $
*
* xcalc.c - a hand calculator for the X Window system
*
* Copyright 1989 by the Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission. M.I.T. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*
* Original Author: John H. Bradley, University of Pennsylvania
* (bradley@cis.upenn.edu)
* March, 1987
* RPN mode added and port to X11 by Mark Rosenstein, MIT Project Athena
* Rewritten to be an Xaw and Xt client by Donna Converse, MIT X Consortium
*/
#include <stdio.h>
#include <math.h>
#include <signal.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xatom.h>
#include <X11/Shell.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Toggle.h>
#include <X11/cursorfont.h>
#include "xcalc.h"
#include "actions.h"
#ifndef IEEE
extern signal_t fperr();
extern signal_t illerr();
#endif
/*
* global data
*/
int rpn = 0; /* Reverse Polish Notation (HP mode) flag */
#define LCD_STR_LEN 32
char dispstr[LCD_STR_LEN]; /* string to show up in the LCD */
Atom wm_delete_window; /* see ICCCM section 5.2.2 */
/*
* local data
*/
static Display *dpy = NULL; /* connection to the X server */
static Widget toplevel=NULL; /* top level shell widget */
static Widget calculator=NULL; /* an underlying form widget */
static Widget LCD = NULL; /* liquid crystal display */
static Widget ind[6]; /* mode indicators in the screen */
static char selstr[LCD_STR_LEN]; /* storage for selections from the LCD */
/* checkerboard used in mono mode */
static XtAppContext xtcontext; /* Toolkit application context */
#define check_width 16
#define check_height 16
static unsigned char check_bits[] = {
0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};
/* command line options specific to the application */
static XrmOptionDescRec Options[] = {
{"-rpn", "rpn", XrmoptionNoArg, (XtPointer)"on"},
{"-stipple", "stipple", XrmoptionNoArg, (XtPointer)"on"}
};
/* resources specific to the application */
static struct resources {
Boolean rpn; /* reverse polish notation (HP mode) */
Boolean stipple; /* background stipple */
Cursor cursor;
} appResources;
#define offset(field) XtOffsetOf(struct resources, field)
static XtResource Resources[] = {
{"rpn", "Rpn", XtRBoolean, sizeof(Boolean),
offset(rpn), XtRImmediate, (XtPointer) False},
{"stipple", "Stipple", XtRBoolean, sizeof(Boolean),
offset(stipple), XtRImmediate, (XtPointer) False},
{"cursor", "Cursor", XtRCursor, sizeof(Cursor),
offset(cursor), XtRCursor, (XtPointer)NULL}
};
#undef offset
void main(argc, argv)
int argc;
char **argv;
{
Arg args[3];
void create_calculator();
void Quit(), Syntax();
toplevel = XtAppInitialize(&xtcontext, "XCalc", Options, XtNumber(Options),
&argc, argv, NULL, NULL, 0);
if (argc != 1) Syntax(argc, argv);
XtSetArg(args[0], XtNinput, True);
XtSetValues(toplevel, args, ONE);
XtGetApplicationResources(toplevel, (XtPointer)&appResources, Resources,
XtNumber(Resources), (ArgList) NULL, ZERO);
create_calculator(toplevel);
XtAppAddActions(xtcontext, Actions, XtNumber(Actions));
XtOverrideTranslations(toplevel,
XtParseTranslationTable("<Message>WM_PROTOCOLS: quit()\n"));
XtRealizeWidget(toplevel);
dpy = XtDisplay(toplevel);
wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
(void) XSetWMProtocols(dpy, XtWindow(toplevel), &wm_delete_window, 1);
XDefineCursor(dpy, XtWindow(toplevel), appResources.cursor);
if (appResources.stipple || (CellsOfScreen(XtScreen(toplevel)) <= 2))
{
Screen *screen = XtScreen(toplevel);
Pixmap backgroundPix;
backgroundPix = XCreatePixmapFromBitmapData
(dpy, XtWindow(toplevel),
(char *)check_bits, check_width, check_height,
WhitePixelOfScreen(screen), BlackPixelOfScreen(screen),
DefaultDepthOfScreen(screen));
XtSetArg(args[0], XtNbackgroundPixmap, backgroundPix);
XtSetValues(calculator, args, ONE);
}
#ifndef IEEE
signal(SIGFPE,fperr);
signal(SIGILL,illerr);
#endif
ResetCalc();
XtAppMainLoop(xtcontext);
}
void create_calculator(shell)
Widget shell;
{
void create_display();
void create_keypad();
rpn = appResources.rpn;
calculator = XtCreateManagedWidget(rpn ? "hp" : "ti", formWidgetClass,
shell, (ArgList) NULL, ZERO);
create_display(calculator);
create_keypad(calculator);
XtSetKeyboardFocus(calculator, LCD);
}
/*
* Do the calculator data display widgets.
*/
void create_display(parent)
Widget parent;
{
Widget bevel, screen;
static Arg args[] = {
{XtNborderWidth, (XtArgVal)0},
{XtNjustify, (XtArgVal)XtJustifyRight}
};
/* the frame surrounding the calculator display */
bevel = XtCreateManagedWidget("bevel", formWidgetClass, parent,
(ArgList) NULL, ZERO);
/* the screen of the calculator */
screen = XtCreateManagedWidget("screen", formWidgetClass, bevel,
(ArgList) NULL, ZERO);
/* M - the memory indicator */
ind[XCalc_MEMORY] = XtCreateManagedWidget("M", labelWidgetClass, screen,
args, XtNumber(args));
/* liquid crystal display */
LCD = XtCreateManagedWidget("LCD", toggleWidgetClass, screen, args,
XtNumber(args));
/* INV - the inverse function indicator */
ind[XCalc_INVERSE] = XtCreateManagedWidget("INV", labelWidgetClass,
screen, args, XtNumber(args));
/* DEG - the degrees switch indicator */
ind[XCalc_DEGREE] = XtCreateManagedWidget("DEG", labelWidgetClass, screen,
args, XtNumber(args));
/* RAD - the radian switch indicator */
ind[XCalc_RADIAN] = XtCreateManagedWidget("RAD", labelWidgetClass, screen,
args, XtNumber(args));
/* GRAD - the grad switch indicator */
ind[XCalc_GRADAM] = XtCreateManagedWidget("GRAD", labelWidgetClass, screen,
args, XtNumber(args));
/* () - the parenthesis indicator */
ind[XCalc_PAREN] = XtCreateManagedWidget("P", labelWidgetClass, screen,
args, XtNumber(args));
}
/*
* Do all the buttons. The application defaults file will give the
* default button placement, default button labels, and default
* actions connected to the buttons. The user can change any of
* these defaults in an environment-specific resource file.
*/
void create_keypad(parent)
Widget parent;
{
static char *Keyboard[] = {
"button1", "button2", "button3", "button4", "button5",
"button6", "button7", "button8", "button9", "button10",
"button11","button12","button13","button14","button15",
"button16","button17","button18","button19","button20",
"button21","button22","button23","button24","button25",
"button26","button27","button28","button29","button30",
"button31","button32","button33","button34","button35",
"button36","button37","button38","button39","button40"
};
register int i;
int n = XtNumber(Keyboard);
if (appResources.rpn) n--; /* HP has 39 buttons, TI has 40 */
for (i=0; i < n; i++)
XtCreateManagedWidget(Keyboard[i], commandWidgetClass, parent,
(ArgList) NULL, ZERO);
}
/*
* Miscellaneous utility routines that interact with the widgets.
*/
/*
* called by math routines to write to the liquid crystal display.
*/
void draw(string)
char *string;
{
Arg args[1];
XtSetArg(args[0], XtNlabel, string);
XtSetValues(LCD, args, ONE);
}
/*
* called by math routines to turn on and off the display indicators.
*/
void setflag(indicator, on)
int indicator;
Boolean on;
{
if (on) XtMapWidget(ind[indicator]);
else XtUnmapWidget(ind[indicator]);
}
/*
* ring the bell.
*/
void ringbell()
{
XBell(dpy, 0);
}
/*
* die.
*/
void Quit()
{
extern void exit();
XtDestroyApplicationContext(xtcontext);
exit(0);
}
/*
* recite and die.
*/
void Syntax(argc, argv)
int argc;
char **argv;
{
register int i;
extern void exit();
(void) fprintf(stderr, "%s: unknown options:", argv[0]);
for (i=1; i <argc; i++)
(void) fprintf(stderr, " %s", argv[i]);
(void) fprintf(stderr, "\n\n");
(void) fprintf(stderr, "Usage: %s", argv[0]);
for (i=0; i < XtNumber(Options); i++)
(void) fprintf(stderr, " [%s]", Options[i].option);
(void) fprintf(stderr, "\n");
XtDestroyApplicationContext(xtcontext);
exit(1);
}
/*
* I use actions on the toggle widget to support selections. This
* means that the user may not do a partial selection of the number
* displayed in the `liquid crystal display.' Copying numbers into
* the calculator is also not supported. So all you can do is copy
* the entire number from the calculator display.
*/
/*ARGSUSED*/
Boolean convert(w, selection, target, type, value, length, format)
Widget w;
Atom *selection;
Atom *target;
Atom *type;
XtPointer *value;
unsigned long *length;
int *format;
{
if (*target == XA_STRING)
{
*type = XA_STRING;
*length = strlen(dispstr);
strncpy(selstr, dispstr, (int)(*length));
*value = selstr;
*format = 8;
return True;
}
return False;
}
/*
* called when xcalc loses ownership of the selection.
*/
/*ARGSUSED*/
void lose(w, selection)
Widget w;
Atom *selection;
{
XawToggleUnsetCurrent(LCD);
}
/*
* called when some other client got the selection.
*/
/*ARGSUSED*/
void done(w, selection, target)
Widget w;
Atom *selection;
Atom *target;
{
selstr[0] = '\0';
}
/*
* called by the selection() action routine, in response to user action.
*/
void do_select(time)
Time time;
{
Boolean state;
Arg args[1];
XtSetArg(args[0], XtNstate, &state);
XtGetValues(LCD, args, 1);
if (state)
XtOwnSelection(LCD, XA_PRIMARY, time, convert, lose, done);
else
selstr[0] = '\0';
}